#pragma once
// Declaration

#include <Windows.h>
#include <string>
#include "CyDelegate.h"
#include "CyNetObjectEnum.h"
#include "CyNetObject.h"
#include "CyNetText.h"
#include "CyNetDummy.h"
#include "CyNetAccelerometer.h"

#define BUFFER_SIZE (2048*1024)

class CyNetTCPClient
{
private:

	UINT_PTR _socket;
	CyDelegate_base * _closeHandler;
	CyDelegate_base * _recvHandler;
	CyDelegate_base * _sendHandler;
	HWND _hWnd;
	char _sendBuffer[BUFFER_SIZE];
	char _recvBuffer[BUFFER_SIZE];
	
	// Recieving status
	bool _recieving;
	int _recievingSize;
	int _recievedSize;
	int _packetCode;

	// Sending status
	bool _sending;
	int _sendingSize;
	int _sentSize;

	void NotifyRead(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
	void NotifyWrite(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
	void NotifyClose(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
	void ResetRecvVariable();
	void ResetSendVariable();

public:
	CyNetTCPClient(HWND parentHWND);
	virtual ~CyNetTCPClient(void);

	CyNetTCPClient& Connect(int PortNo, const char* IPAddress);
	CyNetTCPClient& Disconnect();
	CyNetTCPClient& Send(const CyNetObject& obj);
	static CyNetObject * MakePacket(CyNetObjectEnum type);

	template <class R> void SetCloseHandler(R * obj,
		typename CyDelegate<R>::Handler handler)
	{
		if (obj == NULL || handler == NULL)
		{
			if(_closeHandler != NULL)
				delete _closeHandler;
			_closeHandler = NULL;
		}
		else
		{
			_closeHandler = new typename CyDelegate<R>(obj, handler);
		}
	}

	template <class R> void SetRecvHandler(R * obj,
		typename CyDelegate<R>::Handler handler)
	{
		if (obj == NULL || handler == NULL)
		{
			if(_recvHandler != NULL)
				delete _recvHandler;
			_recvHandler = NULL;
		}
		else
		{
			_recvHandler = new typename CyDelegate<R>(obj, handler);
		}
	}

	template <class R> void SetSendHandler(R * obj,
		typename CyDelegate<R>::Handler handler)
	{
		if (obj == NULL || handler == NULL)
		{
			if(_sendHandler != NULL)
				delete _sendHandler;
			_sendHandler = NULL;
		}
		else
		{
			_sendHandler = new typename CyDelegate<R>(obj, handler);
		}
	}

	friend LRESULT CALLBACK CyNetTCPClientProc(HWND hwnd,
		UINT message, WPARAM wParam, LPARAM lParam);
};